/*
使用c语言接口编写一个udp服务端程序
*/
#include<stdio.h>
#include<unistd.h>
#include<string.h>
#include<arpa/inet.h>//htons字节序转换接口
#include<netinet/in.h>//struct sockaddr_in地址结构协议类型头文件
#include<sys/socket.h>//socket套接字接口头文件
#include<stdlib.h>

//./udp_srv 127.0.0.1 9000
int main(int argc,char* argv[])
{
    if(argc !=3){
        printf("usage:./udp_srv 127.0.0.1 9000\n");
        return -1;
    }
    char *srv_ip = argv[1];
    uint16_t srv_port = atoi(argv[2]);
    //创建套接字 int socket(domain,type,protocal)
    int sockfd = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
    if(sockfd < 0){
        perror("socket error");
        return -1;
    }
    //绑定地址信息int bind(sockfd,sockaddr *addr,addrlen)
    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(srv_port);
    addr.sin_addr.s_addr = inet_addr(srv_ip);
    socklen_t addrlen = sizeof(struct sockaddr_in);
    int ret = bind(sockfd,(struct sockaddr*)&addr,addrlen);
    if(ret<0){
        perror("bind error");
        return -1;
    }
    while(1){
        //接受数据 
        char buf[1024] = {0};
        struct sockaddr_in cliaddr;
        socklen_t addrlen = sizeof(struct sockaddr_in);
        ssize_t ret = recvfrom(sockfd,buf,1023,0,
            (struct sockaddr*)&cliaddr,&addrlen);
        if(ret<0){
            perror("recvfrom error");
             return -1;
        }
        uint16_t cliport = ntohs(cliaddr.sin_port);
        const char *cliip = inet_ntoa(cliaddr.sin_addr);
        printf("cliaddr[%s:%d] say:%s\n",cliip,cliport,buf);

         //响应数据
        printf("server say:");
        fflush(stdout);
        fgets(buf,1023,stdin);//从标准输入-键盘获取一行数据
        ret = sendto(sockfd,buf,strlen(buf),0,
        (struct sockaddr*)&cliaddr,addrlen);
        if(ret<0){
            perror("sendto error");
            return -1;
        }

    }
    //关闭套接字
    close(sockfd);
    return 0;
}

